package com.zf.yichat.utils;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import tk.mybatis.mapper.util.StringUtil;

/**
 * @Title: RSAUtil
 * @Description: RSA加密
 */
@Slf4j
public class RsaUtilWeb extends RSAUtil {
    private static String RSAKeyStore = "C:/RSAKey.txt";
    

    /** 加密算法RSA */
    public static final String KEY_ALGORTHM = "RSA";
    
    private static final int KEY_SIZE=2048;
    
    static BouncyCastleProvider bcp = new BouncyCastleProvider();

    /**
     * @discription 生成密钥对
     */
    public static KeyPair genKeyPairWeb() throws NoSuchAlgorithmException {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(
                    KEY_ALGORTHM, bcp);
            keyPairGen.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGen.generateKeyPair();
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw e;
        }
    }

    /**
     * @discription 获取密钥
     */
    public static KeyPair getKeyPair() throws IOException,ClassNotFoundException {
        FileInputStream fis = null;
        ObjectInputStream oos = null;
        try{
            fis = new FileInputStream(RSAKeyStore);
            oos = new ObjectInputStream(fis);
            KeyPair kp = (KeyPair) oos.readObject();
            return kp;
        }catch(IOException e){
            log.error("获取密钥对异常：", e);
            throw e;
        }finally{
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    log.error("关闭流失败, 原因：", e);
                }
            }
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    log.error("关闭流失败, 原因：", e);
                }
            }
        }
    }

    /**
     * @discription 保存密钥
     */
    public static void saveKeyPair(KeyPair kp) throws IOException {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try{
            fos=new FileOutputStream(RSAKeyStore);
            oos= new ObjectOutputStream(fos);
        }catch(IOException e){
            log.error("保存密钥对异常：", e);
            throw e;
        }finally{
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    log.error("关闭流失败, 原因：", e);
                }
            }
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    log.error("关闭流失败, 原因：", e);
                }
            }
        }
    }

    /**
     * @discription 解密（不支持中文）
     */
    public static String webDecrypt(PrivateKey privateKey, String data)
            throws DecoderException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
        try {
            if (!StringUtil.isEmpty(data)) {
                String[] datas = data.split(" ");
                if (datas != null && datas.length > 1) {
                    StringBuffer deStr = new StringBuffer();
                    for (String dataString : datas) {
                        byte[] raw = Hex.decodeHex(dataString.toCharArray());

                        Cipher cipher = Cipher.getInstance(KEY_ALGORTHM, bcp);
                        cipher.init(Cipher.DECRYPT_MODE, privateKey);

                        deStr.append(new StringBuffer(new String(
                                cipher.doFinal(raw),"UTF-8")).reverse());
                    }
                    return deStr.toString();
                }
            }
            byte[] raw = Hex.decodeHex(data.toCharArray());

            Cipher cipher = Cipher.getInstance(KEY_ALGORTHM, bcp);
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            return new StringBuffer(new String(cipher.doFinal(raw),"UTF-8")).reverse()
                    .toString();
        } catch (DecoderException e) {
            throw e;
        }
    }

}
